package com.lancoo.ccas53.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lancoo.ccas53.entity.*;
import com.lancoo.ccas53.exception.BizException;
import com.lancoo.ccas53.mapper.ActiveTeachMapper;
import com.lancoo.ccas53.mapper.RuleWeekDayMapper;
import com.lancoo.ccas53.mapper.TaskInfoMapper;
import com.lancoo.ccas53.pojo.common.PageInfo;
import com.lancoo.ccas53.pojo.common.ProhibitType;
import com.lancoo.ccas53.pojo.excel.*;
import com.lancoo.ccas53.pojo.vo.MaxPeriodScheme;
import com.lancoo.ccas53.pojo.vo.PeriodSchemeGroupVo;
import com.lancoo.ccas53.service.*;
import com.lancoo.ccas53.util.MyExcelUtils;
import com.lancoo.ccas53.util.PagingUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 课时方案规则 服务实现类
 * </p>
 *
 * @author quin.song
 * @since 2024-05-20
 */
@Service
@Slf4j
public class RuleWeekDayServiceImpl extends ServiceImpl<RuleWeekDayMapper, RuleWeekDay> implements RuleWeekDayService {

    @Resource
    private PeriodSchemeService periodSchemeService;
    @Resource
    private RuleTimeProhibitService ruleTimeProhibitService;
    @Resource
    private MajorGradeService majorGradeService;
    @Resource
    private ActiveTeachService activeTeachService;
    @Resource
    private TypeService typeService;
    @Resource
    private TaskInfoMapper taskInfoMapper;
    @Resource
    private TaskInfoService taskInfoService;
    @Resource
    private ActiveTeachMapper activeTeachMapper;
    @Resource
    private HolidayService holidayService;
    @Resource
    private CollegeService collegeService;
    @Resource
    private RuleWeekDayService ruleWeekDayService;
    @Resource
    private ScheduleService scheduleService;
    @Resource
    private RoomService roomService;
    @Resource
    private TeacherService teacherService;
    @Resource
    private TeachingClassWeekService teachingClassWeekService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean clearTerm(Integer taskId) {
        Long count = scheduleService.lambdaQuery().eq(Schedule::getTaskId, taskId)
                .isNotNull(Schedule::getTimeCode).count();
        if (count > 0) {
            throw new BizException("已进行排课，课时方案暂不支持修改");
        }
        List<TaskInfo> list = taskInfoService.lambdaQuery().eq(TaskInfo::getTaskId, taskId).list();
        if (list != null && list.size() != 0) {
            list.stream().forEach(a -> {
                a.setCycleDay(7);
                a.setPeriodSet(1);
                a.setPeriodMode(1);
                taskInfoMapper.updateById(a);
            });
        }
        ruleTimeProhibitService.lambdaUpdate()
                .eq(RuleTimeProhibit::getTaskId,taskId)
                .eq(RuleTimeProhibit::getOptionType,1)
                .remove();
        return this.lambdaUpdate().eq(RuleWeekDay::getTaskId, taskId).remove();
    }

    @Override
    public List<PeriodSchemeGroupVo> getPeriodSchemes(Integer taskId) {
        List<PeriodSchemeGroupVo> schemeList = new ArrayList<>();
        List<PeriodScheme> periodSchemes = periodSchemeService.lambdaQuery().eq(PeriodScheme::getTaskId, taskId).list();

        //分组
        Map<String, List<PeriodScheme>> periodMap = periodSchemes.stream().collect(Collectors.groupingBy(PeriodScheme::getBaseSchemeId));
        periodMap.forEach((key, value) -> {
            schemeList.add(PeriodSchemeGroupVo.builder()
                    .baseSchemeId(key)
                    .baseSchemeName(value.get(0).getBaseSchemeName())
                    .periodSchemes(value).build());
        });
        return schemeList;
    }

    @Override
    public List<RuleWeekDay> getWeekDays(Integer taskId) {
        List<RuleWeekDay> weekDays = this.lambdaQuery().eq(RuleWeekDay::getTaskId, taskId).list();
        //填充节次信息
        List<PeriodScheme> periodSchemes = periodSchemeService.lambdaQuery().eq(PeriodScheme::getTaskId, taskId).list();

        //分组
        Map<String, List<PeriodScheme>> periodMap = periodSchemes.stream().collect(Collectors.groupingBy(PeriodScheme::getBaseSchemeId));
        weekDays.forEach(day -> {
            day.setPeriodSchemes(periodMap.get(day.getBaseSchemeId()));
        });
        return weekDays;
    }

    @Override
    public MaxPeriodScheme getMaxPeriodScheme(Integer taskId) {
//        List<PeriodSchemeGroupVo> data = this.getPeriodSchemes(taskId);
//        if (CollUtil.isEmpty(data)) {
//            return null;
//        }
//        boolean flag = data.stream()
//                .map(PeriodSchemeGroupVo::getBaseSchemeId)
//                .allMatch(value -> value.equals(data.get(0).getBaseSchemeId()));
//
//        List<PeriodScheme> periodSchemes;
//        periodSchemes = data.stream().max(Comparator.comparing(g -> g.getPeriodSchemes().size())).get().getPeriodSchemes();
        List<String> ids = ruleWeekDayService.lambdaQuery()
                .eq(RuleWeekDay::getTaskId, taskId)
                .list()
                .stream().map(RuleWeekDay::getBaseSchemeId).collect(Collectors.toList());
        if (CollUtil.isEmpty(ids)) {
            throw new BizException("不存在课时方案");
        }
        List<PeriodSchemeGroupVo> data = new ArrayList<>();
        List<PeriodScheme> periodSchemes = periodSchemeService.lambdaQuery()
                .eq(PeriodScheme::getTaskId, taskId)
                .in(PeriodScheme::getBaseSchemeId, ids)
                .list();

        //分组
        Map<String, List<PeriodScheme>> periodMap = periodSchemes.stream().collect(Collectors.groupingBy(PeriodScheme::getBaseSchemeId));
        periodMap.forEach((key, value) -> {
            data.add(PeriodSchemeGroupVo.builder()
                    .baseSchemeId(key)
                    .baseSchemeName(value.get(0).getBaseSchemeName())
                    .periodSchemes(value).build());
        });
        if (CollUtil.isEmpty(data)) {
            return null;
        }
        boolean flag = data.stream()
                .map(PeriodSchemeGroupVo::getBaseSchemeId)
                .allMatch(value -> value.equals(data.get(0).getBaseSchemeId()));

        List<PeriodScheme> periodScheme;
        periodScheme = data.stream().max(Comparator.comparing(g -> g.getPeriodSchemes().size())).get().getPeriodSchemes();

        return MaxPeriodScheme.builder().isUniformly(flag).periodSchemes(periodScheme).build();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateWeekDay(Integer taskId, List<RuleWeekDay> weekDays) {
        Long count = scheduleService.lambdaQuery().eq(Schedule::getTaskId, taskId)
                .isNotNull(Schedule::getTimeCode).count();
        if (count > 0) {
            throw new BizException("已进行排课，课时方案暂不支持修改");
        }
        timeProhibitSuit(taskId, weekDays);


        this.lambdaUpdate().eq(RuleWeekDay::getTaskId, taskId).remove();
        if (weekDays.size() > 0) {
            this.saveBatch(weekDays);
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    public void timeProhibitSuit(Integer taskId, List<RuleWeekDay> weekDays) {
        List<String> removeTimeCodes = getRemoveTimeCodes(taskId, weekDays);
        ruleSetSuit(taskId, removeTimeCodes);
    }

    @Transactional(rollbackFor = Exception.class)
    public void ruleSetSuit(Integer taskId, List<String> removeTimeCodes) {
        if (CollUtil.isNotEmpty(removeTimeCodes)) {
            ruleTimeProhibitService.lambdaUpdate()
                    .eq(RuleTimeProhibit::getTaskId, taskId)
                    .in(RuleTimeProhibit::getTimeCode, removeTimeCodes)
                    .remove();

            List<RuleTimeProhibit> ruleTimeProhibitList = ruleTimeProhibitService.lambdaQuery()
                    .eq(RuleTimeProhibit::getTaskId, taskId)
                    .list();
            if (CollUtil.isEmpty(ruleTimeProhibitList)) {
                roomService.lambdaUpdate()
                        .eq(Room::getTaskId, taskId)
                        .set(Room::getRuleSet, 2)
                        .update();
                teacherService.lambdaUpdate()
                        .eq(Teacher::getTaskId, taskId)
                        .set(Teacher::getRuleSet, 2)
                        .update();
                teachingClassWeekService.ruleSetSuit(taskId, null);
            } else {
                List<Long> ids;
                Map<Integer, List<RuleTimeProhibit>> map = ruleTimeProhibitList.stream().collect(Collectors.groupingBy(RuleTimeProhibit::getOptionType));
                for (Map.Entry<Integer, List<RuleTimeProhibit>> entry : map.entrySet()) {
                    Integer type = entry.getKey();
                    switch (ProhibitType.getByCode(type)) {
                        case ROOM:
                            ids = entry.getValue().stream()
                                    .map(RuleTimeProhibit::getOptionId).distinct()
                                    .collect(Collectors.toList());
                            if (CollUtil.isNotEmpty(ids)) {
                                roomService.lambdaUpdate()
                                        .notIn(Room::getRoomId, ids)
                                        .set(Room::getRuleSet, 2)
                                        .update();
                            }
                            break;
                        case TEACHER:
                            ids = entry.getValue().stream()
                                    .map(RuleTimeProhibit::getOptionId).distinct()
                                    .collect(Collectors.toList());
                            if (CollUtil.isNotEmpty(ids)) {
                                teacherService.lambdaUpdate()
                                        .notIn(Teacher::getTeacherId, ids)
                                        .set(Teacher::getRuleSet, 2)
                                        .update();
                            }
                            break;
                        case TEACHINGCLASS:
                            if (CollUtil.isNotEmpty(entry.getValue())) {
                                teachingClassWeekService.ruleSetSuit(taskId, entry.getValue());
                            }
                            break;
                        default:
                            break;
                    }
                }
            }
        }
    }

    private List<String> getRemoveTimeCodes(Integer taskId, List<RuleWeekDay> weekDays) {
        List<String> oldTimeCode = new ArrayList<>();
        List<String> nowTimeCode = new ArrayList<>();


        Map<String, List<PeriodScheme>> schemeMap = periodSchemeService.lambdaQuery()
                .eq(PeriodScheme::getTaskId, taskId).list()
                .stream().collect(Collectors.groupingBy(PeriodScheme::getBaseSchemeId));

        //原来的课时
        List<RuleWeekDay> oldWeekDays = ruleWeekDayService.lambdaQuery()
                .eq(RuleWeekDay::getTaskId, taskId).list();
        //收集原来的课时
        for (RuleWeekDay weekDay : oldWeekDays) {
            String weekDayCode = weekDay.getWeekDayCode();
            List<PeriodScheme> schemeList = schemeMap.get(weekDay.getBaseSchemeId());
            schemeList.forEach(o -> oldTimeCode.add(weekDayCode + "0" + o.getPeriod()));
        }
        //收集现在的课时
        for (RuleWeekDay weekDay : weekDays) {
            String weekDayCode = weekDay.getWeekDayCode();
            List<PeriodScheme> schemeList = schemeMap.get(weekDay.getBaseSchemeId());
            schemeList.forEach(o -> nowTimeCode.add(weekDayCode + "0" + o.getPeriod()));
        }
        //计算少掉的课时
        return CollUtil.subtractToList(oldTimeCode, nowTimeCode);
    }

    @Override
    public Boolean copyWeekDays(Integer taskId) {
        List<RuleWeekDay> data = this.lambdaQuery()
                .eq(RuleWeekDay::getTaskId, taskId)
                .list();
        data.forEach(a -> a.setBaseSchemeId(a.getBaseSchemeId() + "(copy)"));
        data.forEach(a -> a.setBaseSchemeName(a.getBaseSchemeName() + "(copy)"));
        return this.saveBatch(data);
    }

    @Override
    public List<RuleTimeProhibit> getTimeProhibit(Integer taskId, Integer optionType, Long optionId, Integer hourType) {
        List<RuleTimeProhibit> timeProhibits = ruleTimeProhibitService.lambdaQuery()
                .eq(RuleTimeProhibit::getTaskId, taskId)
                .eq(RuleTimeProhibit::getOptionType, optionType)
                .eq(ObjUtil.isNotNull(optionId), RuleTimeProhibit::getOptionId, optionId)
                .eq(ObjUtil.isNotNull(hourType), RuleTimeProhibit::getHourType, hourType)
                .list();
        return timeProhibits;

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean setTimeProhibit(Integer taskId, Integer optionType, String optionIds, List<RuleTimeProhibit> ruleTimeProhibits) {

        List<Long> ids = new ArrayList<>();
        if (optionType != 1 && StrUtil.isNotEmpty(optionIds)) {
            ids = Arrays.stream(optionIds.split(",")).map(Long::valueOf).collect(Collectors.toList());
        }
        if (CollUtil.isEmpty(ruleTimeProhibits)) {
            throw new BizException("参数不合法");
        }
        //删除原有的禁排规则
        ruleTimeProhibitService.lambdaUpdate()
                .eq(RuleTimeProhibit::getTaskId, taskId)
                .eq(RuleTimeProhibit::getOptionType, optionType)
                .in(optionType != 1 && CollUtil.isNotEmpty(ids),
                        RuleTimeProhibit::getOptionId, ids)
                .remove();

        //保存新地禁排规则
        List<RuleTimeProhibit> saveList = new ArrayList<>();
        if (CollUtil.isEmpty(ids)) {
            saveList.addAll(ruleTimeProhibits);
        } else {
            for (Long optionId : ids) {
                ruleTimeProhibits.forEach(o -> o.setOptionId(optionId));
                saveList.addAll(ruleTimeProhibits);
            }
        }
        ruleTimeProhibitService.saveBatch(saveList);
        return true;
    }

    @Override
    public PageInfo<MajorGrade> getMajorGradeActiveTeachList(Page<MajorGrade> page, Integer taskId, String baseCollegeId, String gradeId, String baseMajorId, String keyword) {
        //获取分页专业年级列表
        Page<MajorGrade> majorGradePage = majorGradeService.lambdaQuery()
                .eq(MajorGrade::getTaskId, taskId)
                .eq(StringUtils.isNotBlank(baseCollegeId), MajorGrade::getBaseCollegeId, baseCollegeId)
                .eq(StringUtils.isNotBlank(gradeId), MajorGrade::getGradeId, gradeId)
                .eq(StringUtils.isNotBlank(baseMajorId), MajorGrade::getBaseMajorId, baseMajorId)
                .and(StringUtils.isNotBlank(keyword), q -> q.like(MajorGrade::getMajorName, keyword).or().like(MajorGrade::getGradeName, keyword))
                .page(page);
        //填充活动教学信息
        List<ActiveTeach> activeTeachList = getActiveTeachByMajorGradeId(taskId, majorGradePage.getRecords()
                .stream().map(MajorGrade::getMajorGradeId).collect(Collectors.toList()));
//                .stream().collect(Collectors.groupingBy(ActiveTeach::getMajorId));

        //activeTeachList中的mojorId有两种情况，0和非0
        majorGradePage.getRecords().forEach(majorGrade -> {
            List<ActiveTeach> list1 = new ArrayList<>();
            List<ActiveTeach> collect = activeTeachList.stream().filter(a -> a.getMajorId() == 0).collect(Collectors.toList());
            Boolean flag = (collect != null && collect.size() != 0);
            activeTeachList.forEach(a -> {
                //如果为非0 ，就需要与majorGrade做对比，相同则插入
                if (a.getMajorId().equals(majorGrade.getMajorGradeId())) {
                    list1.add(a);
                }
//                    list1.add(a);
            });

            if (flag) {
                list1.addAll(collect);
            }
            majorGrade.setActiveTeachList(list1);
        });
        return PagingUtil.formatPageResult(majorGradePage);
    }

    @Override
    public List<ActiveTeach> getActiveTeachByMajorGradeId(Integer taskId, List<Long> majorGradeIds) {
        List<ActiveTeach> activeTeachList = new ArrayList<>();
        if (majorGradeIds.size() == 0) {
            return activeTeachList;
        }
        List<ActiveTeach> list = activeTeachService.lambdaQuery()
                .eq(ActiveTeach::getTaskId, taskId)
                .in(ActiveTeach::getMajorId, majorGradeIds).list();
        //还要再加上majorId参数为0 的数据
        List<ActiveTeach> list1 = activeTeachService.lambdaQuery()
                .eq(ActiveTeach::getTaskId, taskId)
                .eq(ActiveTeach::getMajorId, "0").list();
        list.addAll(list1);
        return list;
    }

    @Override
    public Boolean addActiveTeach(List<ActiveTeach> activeTeachList, Integer taskId) {
        List<Long> majorIds = majorGradeService.lambdaQuery().eq(MajorGrade::getTaskId, taskId).list()
                .stream().map(MajorGrade::getMajorGradeId).collect(Collectors.toList());
        for (ActiveTeach activeTeach : activeTeachList) {
            if (activeTeach.getMajorId().equals(0L)) {
                //设置全校活动，先删除所有专业年级在该周次的教学活动
                activeTeachService.lambdaUpdate().eq(ActiveTeach::getTaskId, taskId).eq(ActiveTeach::getWeek, activeTeach.getWeek()).remove();
                List<ActiveTeach> activeTeaches = new ArrayList<>();
                for (Long majorId : majorIds) {
                    ActiveTeach model = new ActiveTeach();
                    BeanUtils.copyProperties(activeTeach, model);
                    model.setMajorId(majorId);
                    activeTeaches.add(model);
                }
                activeTeachService.saveBatch(activeTeaches);
            } else {
                //先删除该专业年级在此周的教学活动
                activeTeachService.lambdaUpdate()
                        .eq(ActiveTeach::getTaskId, taskId)
                        .eq(ActiveTeach::getMajorId, activeTeach.getMajorId())
                        .eq(ActiveTeach::getWeek, activeTeach.getWeek()).remove();
                activeTeachService.save(activeTeach);
            }
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importHolidaySchedule(HttpServletResponse response, Integer taskId, Integer flag, MultipartFile file) {

        List<ExcelHolidayDto> excelHolidayDtos = this.readHolidayScheduleExcel(file);

        if (flag == 2) {
            //直接删除对应taskId下的假期安排
            holidayService.lambdaUpdate().eq(Holiday::getTaskId, taskId).remove();
        }

        List<Holiday> list = holidayService.lambdaQuery().eq(Holiday::getTaskId, taskId).list();
        List<Holiday> holidays = new ArrayList<>();

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        excelHolidayDtos.forEach(o -> {

            Holiday holiday1 = list.stream().filter(p -> p.getHolidayDate().equals(LocalDate.parse(o.getHolidayDate(), formatter))).findFirst().orElse(null);
            if (ObjUtil.isNull(holiday1)) {
                Holiday holiday = new Holiday();
                holiday.setTaskId(taskId);
                holiday.setHolidayDate(LocalDate.parse(o.getHolidayDate(), formatter));
                holiday.setHolidayName(o.getHolidayName());
                holiday.setFlag("放假".equals(o.getFlag()) ? 1 : 2);
                holidays.add(holiday);
            } else {
                holiday1.setHolidayName(o.getHolidayName());
                holiday1.setFlag("放假".equals(o.getFlag()) ? 1 : 2);
                holidays.add(holiday1);
            }
        });

        if (CollUtil.isNotEmpty(holidays)) {
            holidayService.saveOrUpdateBatch(holidays);
        }
    }

    private List<ExcelHolidayDto> readHolidayScheduleExcel(MultipartFile file) {

        List<ExcelHolidayDto> excelHolidayDtos = new ArrayList<>();
        List<String> expectedHeaders = Arrays.asList(
                "节假日时间", "节假日名称", "节假日安排");
        try {

            InputStream inputStream = file.getResource().getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream, 0);
            //读取表头 判断是否符合预期
            List<String> actualHeaders = reader.readRow(1).stream()
                    .map(Object::toString).filter(org.apache.commons.lang3.StringUtils::isNotBlank)
                    .collect(Collectors.toList());
            if (!expectedHeaders.equals(actualHeaders)) {
                throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
            }

            reader.close();
            ImportParams params = new ImportParams();
            params.setHeadRows(1);
            params.setTitleRows(1);


            excelHolidayDtos = ExcelImportUtil.importExcel(file.getInputStream(), ExcelHolidayDto.class, params);

        } catch (Exception ex) {
            log.info("excel导入教学任务失败:{}", ex.getMessage());
        }

        excelHolidayDtos = excelHolidayDtos.stream().filter(p -> ObjUtil.isNotNull(p.getHolidayDate())).collect(Collectors.toList());

        if (excelHolidayDtos.size() == 0) {
            throw new BizException(5, "导入数据为空，请检查后重新导入");
        }

        return excelHolidayDtos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void exportHolidaySchedule(HttpServletResponse response, Integer taskId) {


        List<ExcelHoliday> excelHolidays = new ArrayList<>();

        TaskInfo taskInfo = taskInfoService.getById(taskId);

        //构建标题
        String title = " {} {}节假日安排导出";
        String format = StrUtil.format(title, taskInfo.getTermName(), taskInfo.getSchoolName());

        List<Holiday> list = holidayService.lambdaQuery().eq(Holiday::getTaskId, taskId).list();

        list.forEach(o -> {

            ExcelHoliday excelHoliday = new ExcelHoliday();
            excelHoliday.setTime(o.getHolidayDate());
            excelHoliday.setHolidayName(o.getHolidayName());
            excelHoliday.setFlag(o.getFlag() == 1 ? "放假" : "补班");
            excelHolidays.add(excelHoliday);

        });

        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss"));

        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-Type", "application/vnd.ms-excel; charset=utf-8");

        MyExcelUtils.exportExcel(excelHolidays,
                format,
                "节假日安排",
                ExcelHoliday.class,
                "节假日安排导出" + time + ".xls", response);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importTeachingActivitySchedule(HttpServletResponse response, Integer taskId, Integer flag, MultipartFile file) {


        List<ExcelTeachingActivityDto> excelTeachingActivities = this.readTeachingActivityExcel(file);

//        if (flag == 2) {
//            activeTeachService.lambdaUpdate().in(ActiveTeach::getTaskId, taskId).remove();
//        }

        List<Type> typeList = typeService.lambdaQuery().eq(Type::getTaskId, taskId).eq(Type::getTypeMode, 1).list();

        Map<String, List<Type>> typeMap = typeList.stream().collect(Collectors.groupingBy(Type::getTypeName));

        List<MajorGrade> majorGrades = majorGradeService.lambdaQuery().eq(MajorGrade::getTaskId, taskId).list();


        List<ActiveTeach> activeTeachList = activeTeachService.lambdaQuery().eq(ActiveTeach::getTaskId, taskId).list();


        //专业map
        Map<String, List<MajorGrade>> majorMap = majorGrades.stream().collect(Collectors.groupingBy(MajorGrade::getMajorName));

        //年级map
        Map<String, List<MajorGrade>> gradeMap = majorGrades.stream().collect(Collectors.groupingBy(MajorGrade::getGradeName));


        //学院map
        List<College> collegeList = collegeService.lambdaQuery().eq(College::getTaskId, taskId).list();

        Map<String, List<College>> collegeMap = collegeList.stream().collect(Collectors.groupingBy(College::getCollegeName));


        Long index = 3L;
        for (ExcelTeachingActivityDto excelTeachingActivity : excelTeachingActivities) {
            excelTeachingActivity.setId(index);
            index++;
        }


        List<ErrorExcelVo> errorExcelVos = new ArrayList<>();
        for (ExcelTeachingActivityDto excelTeachingActivity : excelTeachingActivities) {

            if (StringUtils.isBlank(excelTeachingActivity.getCollegeName()) || !collegeMap.containsKey(excelTeachingActivity.getCollegeName())) {
                ErrorExcelVo errorExcelVo = new ErrorExcelVo();
                errorExcelVo.setErrorIndex(excelTeachingActivity.getId());
                errorExcelVo.setErrorMsg(excelTeachingActivity.getCollegeName() + "学院本学期不存在");
                errorExcelVos.add(errorExcelVo);
            }


            if (StringUtils.isBlank(excelTeachingActivity.getGradeName()) || !gradeMap.containsKey(excelTeachingActivity.getGradeName())) {
                ErrorExcelVo errorExcelVo = new ErrorExcelVo();
                errorExcelVo.setErrorIndex(excelTeachingActivity.getId());
                errorExcelVo.setErrorMsg(excelTeachingActivity.getGradeName() + "年级本学期不存在");
                errorExcelVos.add(errorExcelVo);
            }


            if (StringUtils.isBlank(excelTeachingActivity.getMajorName()) || !majorMap.containsKey(excelTeachingActivity.getMajorName())) {
                ErrorExcelVo errorExcelVo = new ErrorExcelVo();
                errorExcelVo.setErrorIndex(excelTeachingActivity.getId());
                errorExcelVo.setErrorMsg(excelTeachingActivity.getMajorName() + "专业本学期不存在");
                errorExcelVos.add(errorExcelVo);
            }


            if (StringUtils.isBlank(excelTeachingActivity.getActivityType()) || !typeMap.containsKey(excelTeachingActivity.getActivityType())) {
                ErrorExcelVo errorExcelVo = new ErrorExcelVo();
                errorExcelVo.setErrorIndex(excelTeachingActivity.getId());
                errorExcelVo.setErrorMsg(excelTeachingActivity.getActivityType() + "活动本学期未设置不存在");
                errorExcelVos.add(errorExcelVo);
            }
        }


        Integer errorExcelVos1 = errorExcelVos.size();
        if (CollUtil.isNotEmpty(errorExcelVos)) {
            String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss"));
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel; charset=utf-8");

            MyExcelUtils.exportExcel(errorExcelVos,
                    "导入教学活动安排错误信息",
                    "错误信息",
                    ErrorExcelVo.class,
                    "导入教学活动安排错误信息" + time + ".xls", response);
            throw new BizException("导入教学活动安排信息错误");
        }

        if (errorExcelVos1 == 0) {
            List<ErrorExcelVo> errorExcelVos2 = new ArrayList<>();

            List<ActiveTeach> activeTeaches = new ArrayList<>();

            List<Integer> aIds = new ArrayList<>();

            for (ExcelTeachingActivityDto excelTeachingActivity : excelTeachingActivities) {

                College college = collegeMap.get(excelTeachingActivity.getCollegeName()).get(0);

                MajorGrade majorGrade = majorMap.get(excelTeachingActivity.getMajorName()).get(0);
                MajorGrade majorGrade1 = gradeMap.get(excelTeachingActivity.getGradeName()).get(0);


                List<MajorGrade> majorGradeList = majorGrades.stream().filter(p -> p.getBaseCollegeId().equals(college.getBaseCollegeId())
                                && p.getBaseMajorId().equals(majorGrade.getBaseMajorId()) && p.getGradeId().equals(majorGrade1.getGradeId()))
                        .collect(Collectors.toList());


                if (CollUtil.isNotEmpty(majorGradeList)) {
                    majorGradeList.forEach(o -> {
                        ActiveTeach activeTeachList1 = activeTeachList.stream().filter(p -> p.getMajorId().equals(o.getMajorGradeId())
                                && p.getWeek().equals(Integer.valueOf(excelTeachingActivity.getWeek()))).findFirst().orElse(null);
                        if (ObjUtil.isNull(activeTeachList1)) {
                            ActiveTeach activeTeach = new ActiveTeach();
                            activeTeach.setTaskId(taskId);
                            activeTeach.setMajorId(o.getMajorGradeId());
                            activeTeach.setTypeId(typeMap.get(excelTeachingActivity.getActivityType()).get(0).getTypeId());
                            activeTeach.setTypeName(typeMap.get(excelTeachingActivity.getActivityType()).get(0).getTypeName());
                            activeTeach.setWeek(Integer.parseInt(excelTeachingActivity.getWeek()));
                            activeTeach.setIcon(typeMap.get(excelTeachingActivity.getActivityType()).get(0).getIcon());
                            activeTeaches.add(activeTeach);
                        } else {
                            aIds.add(activeTeachList1.getActiveId());
                            ActiveTeach activeTeach = new ActiveTeach();
                            activeTeach.setTaskId(taskId);
                            activeTeach.setMajorId(o.getMajorGradeId());
                            activeTeach.setTypeId(typeMap.get(excelTeachingActivity.getActivityType()).get(0).getTypeId());
                            activeTeach.setTypeName(typeMap.get(excelTeachingActivity.getActivityType()).get(0).getTypeName());
                            activeTeach.setWeek(Integer.parseInt(excelTeachingActivity.getWeek()));
                            activeTeach.setIcon(typeMap.get(excelTeachingActivity.getActivityType()).get(0).getIcon());
                            activeTeaches.add(activeTeach);
                        }
                    });
                } else {
                    ErrorExcelVo errorExcelVo = new ErrorExcelVo();
                    errorExcelVo.setErrorIndex(excelTeachingActivity.getId());
                    errorExcelVo.setErrorMsg(excelTeachingActivity.getCollegeName() + excelTeachingActivity.getGradeName() + excelTeachingActivity.getMajorName() + "不存在");
                    errorExcelVos2.add(errorExcelVo);
                }
            }


            Integer errorExcelVos3 = errorExcelVos2.size();
            if (CollUtil.isNotEmpty(errorExcelVos)) {
                String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss"));
                response.setCharacterEncoding("UTF-8");
                response.setHeader("content-Type", "application/vnd.ms-excel; charset=utf-8");

                MyExcelUtils.exportExcel(errorExcelVos,
                        "导入教学活动安排错误信息",
                        "错误信息",
                        ErrorExcelVo.class,
                        "导入教学活动安排错误信息" + time + ".xls", response);
                throw new BizException("导入教学活动安排错误信息");
            }

            if (errorExcelVos3 == 0) {

                if (CollUtil.isNotEmpty(aIds)) {
                    activeTeachService.lambdaUpdate().in(ActiveTeach::getActiveId, aIds).remove();
                }

                if (CollUtil.isNotEmpty(activeTeaches)) {
                    activeTeachService.saveOrUpdateBatch(activeTeaches);
                }

            }


        }
    }

    private List<ExcelTeachingActivityDto> readTeachingActivityExcel(MultipartFile file) {


        List<ExcelTeachingActivityDto> excelTeachingActivities = new ArrayList<>();
        List<String> expectedHeaders = Arrays.asList(
                "学院名称", "专业", "年级名称", "周次", "活动类型", "是否排课");
        try {

            InputStream inputStream = file.getResource().getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream, 0);
            //读取表头 判断是否符合预期
            List<String> actualHeaders = reader.readRow(1).stream()
                    .map(Object::toString).filter(org.apache.commons.lang3.StringUtils::isNotBlank)
                    .collect(Collectors.toList());
            if (!expectedHeaders.equals(actualHeaders)) {
                throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
            }

            reader.addHeaderAlias("学院名称", "collegeName");
            reader.addHeaderAlias("专业", "majorName");
            reader.addHeaderAlias("年级名称", "gradeName");
            reader.addHeaderAlias("周次", "week");
            reader.addHeaderAlias("活动类型", "activityType");
            reader.addHeaderAlias("是否排课", "isSchedule");


            excelTeachingActivities = reader.read(1, 2, ExcelTeachingActivityDto.class);
            reader.close();
        } catch (Exception ex) {
            log.info("excel导入教学任务失败:{}", ex.getMessage());
        }

        if (excelTeachingActivities.size() == 0) {
            throw new BizException(5, "导入数据为空，请检查后重新导入");
        }

        return excelTeachingActivities;


    }


    @Override
    public void exportTeachingActivitySchedule(HttpServletResponse response, Integer taskId, String baseCollegeId, String gradeId, String baseMajorId, String keyword, Integer currentPage, Integer pageSize) {


        List<ExcelTeachingActivity> excelTeachingActivities = new ArrayList<>();


        TaskInfo taskInfo = taskInfoService.getById(taskId);

        List<MajorGrade> majorGrades = majorGradeService.lambdaQuery().eq(MajorGrade::getTaskId, taskId).list();

        List<College> collegeList = collegeService.lambdaQuery().eq(College::getTaskId, taskId).list();


        String format = "";

        if (CollUtil.isNotEmpty(majorGrades)) {
            List<MajorGrade> gradeList = new ArrayList<>();

            List<MajorGrade> majorGradeList = new ArrayList<>();


            List<College> colleges = new ArrayList<>();
            if (StringUtils.isNotBlank(gradeId)) {
                gradeList = majorGrades.stream().filter(p -> p.getGradeId().equals(gradeId)).collect(Collectors.toList());

            }
            if (StringUtils.isNotBlank(baseMajorId)) {
                majorGradeList = majorGrades.stream().filter(p -> p.getBaseMajorId().equals(baseMajorId)).collect(Collectors.toList());
            }

            if (StringUtils.isNotBlank(baseCollegeId)) {
                colleges = collegeList.stream().filter(p -> p.getBaseCollegeId().equals(baseCollegeId)).collect(Collectors.toList());
            }

            MajorGrade majorGrade = new MajorGrade();
            if (CollUtil.isNotEmpty(gradeList)) {
                majorGrade = gradeList.get(0);
            }

            MajorGrade majorGrade1 = new MajorGrade();

            if (CollUtil.isNotEmpty(majorGradeList)) {
                majorGrade1 = majorGradeList.get(0);

            }
            College college = new College();

            if (CollUtil.isNotEmpty(colleges)) {
                college = colleges.get(0);
            }


            //构建标题
            String title = " {} {}教学活动安排导出 " + "\n" + "院系:{}" + "\n" + "年级:{}" + "\n" + "专业:{}";
            format = StrUtil.format(title, taskInfo.getTermName(), taskInfo.getSchoolName(),
                    StringUtils.isBlank(baseCollegeId) ? "全部院系" : college.getCollegeName(),
                    StringUtils.isBlank(gradeId) ? "全部年级" : majorGrade.getGradeName(), StringUtils.isBlank(baseMajorId) ? "全部专业" : majorGrade1.getMajorName());
        }


        List<Type> types = typeService.lambdaQuery().eq(Type::getTaskId, taskId).list();


        Page<MajorGrade> page = new Page<>(1, -1);

        PageInfo<MajorGrade> majorGradeActiveTeachList = this.getMajorGradeActiveTeachList(page, taskId, baseCollegeId, gradeId, baseMajorId, keyword);

        List<MajorGrade> list = majorGradeActiveTeachList.getList();


        list.forEach(o -> {

            List<ActiveTeach> activeTeachList = o.getActiveTeachList();

            activeTeachList.forEach(a -> {

                ExcelTeachingActivity excelTeachingActivity = new ExcelTeachingActivity();
                excelTeachingActivity.setCollegeName(o.getCollegeName());
                excelTeachingActivity.setGradeName(o.getGradeName());
                excelTeachingActivity.setMajorName(o.getMajorName());
                excelTeachingActivity.setWeek(a.getWeek());
                excelTeachingActivity.setActivityType(a.getTypeName());

                List<Type> typeList = types.stream().filter(p -> p.getTypeId().equals(a.getTypeId())).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(typeList)) {
                    Type type = typeList.get(0);
                    excelTeachingActivity.setIsSchedule(type.getFlag() == 1 ? "不排课" : "可排课");
                } else {
                    excelTeachingActivity.setIsSchedule("未设置类型");
                }
                excelTeachingActivities.add(excelTeachingActivity);
            });
        });


        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss"));

        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-Type", "application/vnd.ms-excel; charset=utf-8");

        MyExcelUtils.exportExcel(excelTeachingActivities,
                format,
                "教学活动安排",
                ExcelTeachingActivity.class,
                "教学活动安排表" + time + ".xls", response);


    }
}
